package com.cauli.account.login.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cauli.account.config.model.dto.ConfigDetailDTO;
import com.cauli.account.config.model.dto.ConfigQueryDTO;
import com.cauli.account.config.service.ConfigService;
import com.cauli.account.login.model.dto.LoginDTO;
import com.cauli.account.login.model.dto.RegisterDTO;
import com.cauli.account.login.service.ImgVerifyCodeService;
import com.cauli.account.login.service.LoginService;
import com.cauli.account.user.mapper.UserMapper;
import com.cauli.account.user.model.entity.User;
import com.cauli.account.user.service.UserService;
import com.cauli.utils.exception.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author Cauli
 * @date 2022/12/13 10:04
 * @description 登录 服务实现类
 */
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private ConfigService configService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ImgVerifyCodeService imgVerifyCodeService;

    @Override
    public SaTokenInfo login(HttpServletRequest request, LoginDTO loginDTO) {
        ConfigQueryDTO configQueryDTO = new ConfigQueryDTO();
        configQueryDTO.setGroupName("login");
        // 获取系统设置
        ConfigDetailDTO configDetailDTO = configService.getConfig(configQueryDTO);
        if (configDetailDTO.getCaptchaMode()) {
            imgVerifyCodeService.checkCaptcha(loginDTO.getVerifyCodeUUID(), loginDTO.getVerifyCode());
        }

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, loginDTO.getUsername())
                .eq(User::getPassword, SecureUtil.md5(loginDTO.getPassword()));
        User user = userService.getOne(queryWrapper);
        if (user == null) {
            throw new MyException("用户名或密码错误");
        }

        // 登录
        StpUtil.login(user.getUserId());

        // 更新最后登录IP和登录时间
        user.setLoginIp(ServletUtil.getClientIP(request));
        user.setLoginDate(new Date());
        userService.updateById(user);

        // 在登录时缓存user对象
        StpUtil.getSession().set("user", user);
        StpUtil.getSession().set("userId", user.getUserId());

        return StpUtil.getTokenInfo();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterDTO registerDTO) {
        // 检测用户名是否被占用
        this.checkIsDuplicated(registerDTO.getUsername());
        registerDTO.setUserId(Long.valueOf(IdUtil.getSnowflakeNextIdStr()));
        registerDTO.setPassword(SecureUtil.md5(registerDTO.getPassword()));
        registerDTO.setRoleId(2L);
        registerDTO.setStatus(1);
        registerDTO.setCreateTime(DateUtil.date());
        registerDTO.setUpdateTime(DateUtil.date());
        registerDTO.setCreatorId(registerDTO.getUserId());
        registerDTO.setUpdaterId(registerDTO.getUserId());
        // 注册
        userMapper.register(registerDTO);
    }

    /**
     * 检测用户名是否被占用
     *
     * @param username
     */
    private void checkIsDuplicated(String username) {
        if (userMapper.exists(new LambdaQueryWrapper<User>().eq(User::getUsername, username))) {
            throw new MyException("该用户名已被占用");
        }
    }
}
